package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;

import view.CAImageBuffer;
import view.ImageFrame;
import view.Planete;
import view.colorant.AltitudeColorant;
import view.colorant.AnimalColorant;
import view.colorant.MultiColorant;
import view.colorant.TypeTerrainColorant;
import carte.Carte;
import carte.Cellule;
import carte.Position;
import carte.element.Fire;
import carte.element.Mana;
import carte.element.Water;
import carte.population.Vachmouth;
import carte.terrain.Land;

public class MondeDeNemo implements MouseListener, ActionListener, KeyListener {

	// colorants possibles
	static AltitudeColorant altitudeColorant = new AltitudeColorant(
			Carte.MAX_ALTITUDE);
	static TypeTerrainColorant typeTerrainColorant = new TypeTerrainColorant();
	static AnimalColorant animalColorant = new AnimalColorant();

	MultiColorant currentColour;
	//Etat actuel du Menu
	private String currentGodPower;
	private String currentZoom;
	
	JCheckBoxMenuItem jmiColorAltitude, jmiColorType, jmiColorAnimal;
	JMenuItem jmiSendWater, jmiSendFire, jmiSendMana, jmiBuildVolcano,
			jmiSendNice;// , jmiSendBad;
	JMenuItem jmiZoomPlus, jmiZoomMinus;
	
	Planete world;
	CAImageBuffer image;
	ImageFrame imageFrame;

	int delai = 250;// 100; // -- delay before refreshing display -- program
	// is hold during delay, even if no screen update was
	// requested. USE WITH CARE.
	int nombreDePasMaximum = Integer.MAX_VALUE;
	int displaySpeed = 1;// 50; // from 1 to ...
	private Random rand;
	//taille de la fenêtre
	public static final int World_size = 200;

	public MondeDeNemo() {
		// initialisation generale

		currentColour = new MultiColorant();
		currentColour.add(altitudeColorant);
		currentColour.add(typeTerrainColorant);
		currentColour.add(animalColorant);

		/* taille du monde */
		int dx = World_size;
		int dy = World_size;

		int displayWidth = dx; // 200
		int displayHeight = dy; // 200

		// pick dimension for display
		if (displayWidth < 200)
			displayWidth = 200;
		else if (displayWidth > 600)
			displayWidth = 600;
		else if (displayWidth < 300)
			displayWidth = displayWidth * 2;
		if (displayHeight < 200)
			displayHeight = 200;
		else if (displayHeight > 600)
			displayHeight = 600;
		else if (displayHeight < 300)
			displayHeight = displayHeight * 2;

		rand = new Random();

		// Creates a menubar for a JFrame
		JMenuBar menuBar = new JMenuBar();

		JMenu jmColorant = new JMenu("Colorant");
		menuBar.add(jmColorant);
		jmiColorType = new JCheckBoxMenuItem("par type", true);
		jmiColorAltitude = new JCheckBoxMenuItem("par altitude", true);
		jmiColorAnimal = new JCheckBoxMenuItem("voir les populations", true);
		jmColorant.add(jmiColorType);
		jmColorant.add(jmiColorAltitude);
		jmColorant.add(jmiColorAnimal);
		jmiColorAltitude.addActionListener(this);
		jmiColorType.addActionListener(this);
		jmiColorAnimal.addActionListener(this);

		JMenu jmSend = new JMenu("Envoyer");
		menuBar.add(jmSend);
		ButtonGroup mbgSend = new ButtonGroup();
		jmiSendWater = new JRadioButtonMenuItem("Eau", true);
		jmiSendFire = new JRadioButtonMenuItem("Feu");
		jmiSendMana = new JRadioButtonMenuItem("Mana");
		jmiBuildVolcano = new JRadioButtonMenuItem("Volcan");
		jmiSendNice = new JRadioButtonMenuItem("Vachmouths");
		// jmiSendBad = new JRadioButtonMenuItem("Méchants");
		currentGodPower = "Water";
		mbgSend.add(jmiSendWater);
		mbgSend.add(jmiSendFire);
		mbgSend.add(jmiSendMana);
		mbgSend.add(jmiBuildVolcano);
		mbgSend.add(jmiSendNice);
		// mbgSend.add(jmiSendBad);
		jmSend.add(jmiSendWater);
		jmSend.add(jmiSendFire);
		jmSend.add(jmiSendMana);
		jmSend.add(jmiBuildVolcano);
		jmSend.add(jmiSendNice);
		// jmSend.add(jmiSendBad);
		jmiSendWater.addActionListener(this);
		jmiSendFire.addActionListener(this);
		jmiSendMana.addActionListener(this);
		jmiBuildVolcano.addActionListener(this);
		jmiSendNice.addActionListener(this);
		// jmiSendBad.addActionListener(this);

		//MENU DU ZOOM
		JMenu jmZoom = new JMenu("Zoom");
		menuBar.add(jmZoom);
		ButtonGroup mbgZoom = new ButtonGroup();
		jmiZoomPlus = new JRadioButtonMenuItem("Zoom +", true);
		jmiZoomMinus = new JRadioButtonMenuItem("Zoom -");
		mbgZoom.add(jmiZoomPlus);
		mbgZoom.add(jmiZoomMinus);
		jmZoom.add(jmiZoomPlus);
		jmZoom.add(jmiZoomMinus);
		jmiZoomPlus.addActionListener(this);
		jmiZoomMinus.addActionListener(this);
		currentZoom = "Plus";
		
		image = new CAImageBuffer(dx, dy);
		imageFrame = ImageFrame.makeFrame("Evolution World", image, delai,
				displayWidth, displayHeight);
		imageFrame.addMouseListener(this);
		imageFrame.addKeyListener(this);
		imageFrame.setFocusable(true);
		imageFrame.setJMenuBar(menuBar);
		
		// initialise l'ecosysteme
		world = new Planete(new Carte(dx, dy), imageFrame.getWidth(), imageFrame.getHeight());
		
	}

	public static void main(String[] args) {

		int it = 0;
		MondeDeNemo m = new MondeDeNemo();

		// mise a jour de l'etat du monde

		while (it != m.nombreDePasMaximum) {
			// 1 - display

			if (it % m.displaySpeed == 0)
				m.refresh();

			// 2 - update

			m.world.step();

			// 3 - iterate

			it++;

			try {
				Thread.sleep(m.delai);
			} catch (InterruptedException e) {
			}
		}
	}

	// permet de rafraichir l'affichage de l'ecran
	public void refresh() {
		world.display(image, currentColour);
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {

	}

	@Override
	public void mouseExited(MouseEvent arg0) {

	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// on recupere la position de la souris dans la map
		Position pos = world.getClickPosition(arg0.getX(), arg0.getY());

		// si on a cliqué avec le bouton gauche
		if (arg0.getButton() == arg0.BUTTON1) {
			// a present on regarde le type de pouvoir de Dieu active

			// L'EAU
			if (currentGodPower.equals("Water")) {
				// A present on va recuperer toutes les cases autour de cette
				// case
				// aussi et on va faire pleuvoir
				ArrayList<Cellule> cells = world.getMap().getCellRange(
						pos.getX(), pos.getY(), Water.RANGE_GOD);
				for (Cellule cell : cells) {
					// on rajoute de l'eau mais selon la proba RATIO_GOD
					if (rand.nextFloat() <= Water.RATIO_GOD) {
						cell.addFluid(Water.getTypeName(), Water.QUANTITY_GOD);
						// cell.addFluid(Mana.getTypeName(), Mana.QUANTITY_GOD);
					}
				}
			}

			// LE MANA
			else if (currentGodPower.equals("Mana")) {
				// A present on va recuperer toutes les cases autour de cette
				// case
				// aussi et on va faire pleuvoir
				ArrayList<Cellule> cells = world.getMap().getCellRange(
						pos.getX(), pos.getY(), Mana.RANGE_GOD);
				for (Cellule cell : cells) {
					// on rajoute de l'eau mais selon la proba RATIO_GOD
					if (rand.nextFloat() <= Mana.RATIO_GOD) {
						cell.addFluid(Mana.getTypeName(), Mana.QUANTITY_GOD);
					}
				}
			}

			// LE FEU
			else if (currentGodPower.equals("Fire")) {
				// A present on va recuperer toutes les cases autour de cette
				// case
				// aussi et on va toutes les enflammer
				ArrayList<Cellule> cells = world.getMap().getCellRange(
						pos.getX(), pos.getY(), Fire.RANGE_GOD);
				for (Cellule cell : cells) {
					// on essaye d'enflammer la case
					cell.addFire();
				}
			}

			// VOLCAN
			else if (currentGodPower.equals("Volcano")) {
				// placer un volcan sur la carte
				world.getMap().getCell(pos.getX(), pos.getY())
						.setLand(Land.Volcano());
			}

			// GENTIL ANIMAL
			else if (currentGodPower.equals(Vachmouth.getTypeName())) {
				// A present on va recuperer toutes les cases autour de cette
				// case
				// aussi et on va faire pleuvoir
				ArrayList<Cellule> cells = world.getMap().getCellRange(
						pos.getX(), pos.getY(), Vachmouth.RANGE_GOD);
				for (Cellule cell : cells) {
					// on rajoute de l'eau mais selon la proba RATIO_GOD
					if (rand.nextFloat() <= Vachmouth.RATIO_GOD) {
						cell.addAnimal(new Vachmouth());
					}
				}
			}
		}
		//sinon on a cliqué sur le bouton droit et c'est pour gérer le niveau de zoom
		else if(arg0.getButton() == arg0.BUTTON3){
			if(currentZoom.compareTo("Plus") == 0){
				world.zoomPlus(arg0.getX(), arg0.getY());
			}
			else if(currentZoom.compareTo("Minus") == 0){
				world.zoomMinus(arg0.getX(), arg0.getY());
			}
		}
		refresh();
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if (arg0.getSource() == jmiColorAltitude) {
			currentColour.set(altitudeColorant, jmiColorAltitude.getState());
		} else if (arg0.getSource() == jmiColorType) {
			currentColour.set(typeTerrainColorant, jmiColorType.getState());
		} else if (arg0.getSource() == jmiColorAnimal) {
			currentColour.set(animalColorant, jmiColorAnimal.getState());
		} else if (arg0.getSource() == jmiSendWater) {
			currentGodPower = "Water";
		} else if (arg0.getSource() == jmiSendFire) {
			currentGodPower = "Fire";
		} else if (arg0.getSource() == jmiSendMana) {
			currentGodPower = "Mana";
		} else if (arg0.getSource() == jmiBuildVolcano) {
			currentGodPower = "Volcano";
		} else if (arg0.getSource() == jmiSendNice) {
			currentGodPower = Vachmouth.getTypeName();
		} else if (arg0.getSource() == jmiZoomPlus) {
			currentZoom = "Plus";
		} else if (arg0.getSource() == jmiZoomMinus) {
			currentZoom = "Minus";
		}
		/*
		}
		 * else if (arg0.getSource() == jmiSendBad) { currentGodPower =
		 * Tigre.getTypeName(); }
		 */
		refresh();
	}

	@Override
	public void keyPressed(KeyEvent arg0) {	
		if (arg0.getKeyCode() == KeyEvent.VK_RIGHT ) {
			world.moveZoom(1, 0);
		}
		else if (arg0.getKeyCode() == KeyEvent.VK_LEFT ) {
			world.moveZoom(-1, 0);
		}
		else if (arg0.getKeyCode() == KeyEvent.VK_UP ) {
			world.moveZoom(0, -1);
		}
		else if (arg0.getKeyCode() == KeyEvent.VK_DOWN ) {
			world.moveZoom(0, 1);
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
	}

}
